<?php

namespace Tests;

use Illuminate\Console\Command;
use Illuminate\Database\MySqlConnection;
use Illuminate\Support\Facades\DB;
use Laravel\Dusk\TestCase as BaseTestCase;
use Facebook\WebDriver\Chrome\ChromeOptions;
use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\Remote\DesiredCapabilities;
use Tests\Concerns\ResizeBrowser;
use Tests\Utils\PanxData;

abstract class DuskTestCase extends BaseTestCase
{
    use CreatesApplication;
    use ResizeBrowser;

    const WEB_DRIVER_URL = 'http://localhost:9515';
    /**
     * @throws \Exception
     */
    protected function setUp()
    {
        $this->initApp();
        // should after app initialized because config method not loaded
        $this->checkDuskEnvFile();
        $this->checkDatabaseName();

        parent::setUp();
    }

    /**
     * 测试确认使用 .env.dusk.{APP_ENV} 文件
     *
     * @throws \Exception
     */
    private function checkDuskEnvFile(): void
    {
        if(! count(glob(base_path('.env.dusk.*')))) {
            $env = config('app.env');
            $file_name = ".env.dusk.{$env}";

            echo("You Should create $file_name for Dusk test");
            exit(1);
        };
    }

    /**
     * Prepare for Dusk test execution.
     *
     * @beforeClass
     * @return void
     */
    public static function prepare()
    {
        /**
         * linux 可能不能正常启动，需要手动运行 vendor/laravel/dusk/bin/chromedriver-linux [-port=9515]
         *
         * 如果使用 safari ，使用下面的命令先打开 safari 即可
         * @link https://webkit.org/blog/6900/webdriver-support-in-safari-10/ - 开启开发者模式，同意自动化
         * @example
         *     再打开 /usr/bin/safaridriver -p 9515
         */
        static::startChromeDriver();
    }

    /**
     * Create the RemoteWebDriver instance.
     *
     * @return \Facebook\WebDriver\Remote\RemoteWebDriver
     */
    protected function driver()
    {
        /**
         * @link https://sites.google.com/a/chromium.org/chromedriver/home chrome web driver
         */
        return RemoteWebDriver::create(
            self::WEB_DRIVER_URL,
            /**
             * https://github.com/facebook/php-webdriver - php webdriver 的文档
             */
            $this->getWebCapByEnv()
        );
    }

    /**
     * @return DesiredCapabilities
     */
    protected function getWebCapByEnv()
    {
        $args = $this->getDefaultArgs();

        switch (config(PanxData::DUSK_ENV_KEY)) {

            case PanxData::DUSK_ENV_ADMIN:
                return $this->getChromeCap($args);

            case PanxData::DUSK_ENV_WECHAT:
                return $this->getWechatCap($args);

            case PanxData::DUSK_ENV_MOBILE:
                return $this->getIPhoneCap($args);

            case PanxData::DUSK_ENV_APP:
                return $this->getAppCap($args);

            default :
                throw new \RuntimeException('You Should Specify What Web Platform Use In Config');
        }
    }

    /**
     * @param $args
     *
     * @return DesiredCapabilities
     */
    protected function getChromeCap(array $args): DesiredCapabilities
    {
        $args [] = '--window-size=1920,1080'; // PC

        $options = (new ChromeOptions)->addArguments($args);

        /**
         * https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities
         */
        return DesiredCapabilities::chrome()
            ->setCapability(ChromeOptions::CAPABILITY, $options);
    }

    /**
     *
     * @return DesiredCapabilities
     */
    protected function getSafariCap(): DesiredCapabilities
    {
        return DesiredCapabilities::safari();
    }

    /**
     *
     * @return DesiredCapabilities
     */
    protected function getFirefoxCap(): DesiredCapabilities
    {
        return DesiredCapabilities::firefox();
    }

    /**
     * @param $args
     *
     * @return DesiredCapabilities
     */
    protected function getIPhoneCap(array $args): DesiredCapabilities
    {
        $args [] = '--window-size=375,667'; // iphone

        $options = (new ChromeOptions)->addArguments($args);

        return DesiredCapabilities::iphone()
            ->setCapability(ChromeOptions::CAPABILITY, $options);
    }

    /**
     * @param $args
     *
     * @return DesiredCapabilities
     */
    protected function getWechatCap(array $args): DesiredCapabilities
    {
        $args [] = '--window-size=375,667'; // iphone

        $options = (new ChromeOptions)->addArguments($args);

        /**
         * https://sites.google.com/a/chromium.org/chromedriver/mobile-emulation - 这里只有 java / python / ruby 的示例
         * https://sites.google.com/a/chromium.org/chromedriver/capabilities - chromeOptions object 一节处有 mobileEmulation 的参数
         */
        $options->setExperimentalOption('mobileEmulation', [
            'userAgent' => 'Mozilla/5.0 (Linux; Android 5.1.1; vivo X7Plus Build/LMY47V; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/57.0.2987.132 MQQBrowser/6.2 TBS/044205 Mobile Safari/537.36 MicroMessenger/6.7.2.1340(0x26070238) NetType/WiFi Language/zh_CN',
        ]);
        
        return DesiredCapabilities::iphone()
            ->setCapability(ChromeOptions::CAPABILITY, $options);
    }

    /**
     * @param $args
     *
     * @return DesiredCapabilities
     */
    protected function getAppCap(array $args): DesiredCapabilities
    {
        $args [] = '--window-size=768,1024'; // iPad

        $options = (new ChromeOptions)->addArguments($args);

        return DesiredCapabilities::ipad()
            ->setCapability(ChromeOptions::CAPABILITY, $options);
    }

    /**
     * @link https://developers.google.com/web/updates/2017/04/headless-chrome - 参数参考
     * @link https://developer.chrome.com/extensions/i18n#locales-testing - --lang 参数
     *
     * @return array
     */
    protected function getDefaultArgs(): array
    {
        $args = [
            '--disable-gpu', // disable webGL
            '--no-gpu', // prevent Lost UI shared context error
            '--disable-software-rasterizer',

            '--lang=zh-CN', // default chinese locale
            '--no-sandbox', // for centOS
        ];

        if (getenv('HEADLESS') || config('pkx.dusk.headless')) {
            $args []= '--headless';
        }

        return $args;
    }
    
    private function checkDatabaseName(): void
    {
        /** @var MySqlConnection $con */
        $con = DB::connection();
        $db = $con->getDatabaseName();
        $test_prefix = 'ci_';

        if (! starts_with($db, $test_prefix)) {
            echo("Your Database name is [$db], should start with [$test_prefix] for Dusk test");
            exit(1);
        }
    }

    protected function initApp(): void
    {
        if (! $this->app) {
            $this->refreshApplication();
        }
    }
}
